﻿Imports Commander_Wars.Spieletools
Public Class Wegsuchsystem
#Region "Variablen"
    Enum Sucharten
        ''' <summary>
        ''' Normale Suche
        ''' </summary>
        ''' <remarks></remarks>
        Normal
        ''' <summary>
        ''' Bis wir einen Feind gefunden haben dann Rückgabe=true
        ''' </summary>
        ''' <remarks></remarks>
        FEinheit
        ''' <summary>
        ''' Bis wir einen Besetzung gefunden haben dann Rückgabe=true
        ''' </summary>
        ''' <remarks></remarks>
        Besetzung
        ''' <summary>
        ''' Bis wir einen Feind,Besetzung gefunden haben Rückgabe as integer
        ''' </summary>
        ''' <remarks></remarks>
        FEinheitBesetzung
        ''' <summary>
        ''' Bis wir einen Feind gefunden haben Rückgabe as integer
        ''' </summary>
        ''' <remarks></remarks>
        FEinheitDaurRückgabe
        ''' <summary>
        ''' Bis wir einen Besetzung gefunden haben Rückgabe as integer
        ''' </summary>
        ''' <remarks></remarks>
        BesetzungDauerRückgabe
        ''' <summary>
        ''' Bis wir einen Feind,Besetzung gefunden haben Rückgabe as Point
        ''' </summary>
        ''' <remarks></remarks>
        TransportFEinheitBesetzung
        ''' <summary>
        ''' Bis wir einen Feind gefunden haben Rückgabe as Point
        ''' </summary>
        ''' <remarks></remarks>
        TransportFEinheitDaurRückgabe
        ''' <summary>
        ''' Bis wir einen Besetzung gefunden haben Rückgabe as Point
        ''' </summary>
        ''' <remarks></remarks>
        TransportBesetzungDauerRückgabe
        ''' <summary>
        ''' Gibt es einen Feind der uns hier erreichen kann!
        ''' </summary>
        ''' <remarks></remarks>
        KannAngegriffenWerden
        ''' <summary>
        ''' Können wir dieses Feld erreichen
        ''' </summary>
        ''' <remarks></remarks>
        ZumZiel
        ''' <summary>
        ''' Sucht bis wir n-Bewegungspunkte verbraucht haben!
        ''' </summary>
        ''' <remarks></remarks>
        Dauer
    End Enum
    Enum SuchartenEinheiten
        EinheitenBerücksichtigen
        NichtGezogeneEinheitenIgnorieren
        AlleEinheitenIgnorieren
        EigeneEinheitenIgnorieren
    End Enum

    Dim Feld As ObjektSpielfeld
    Dim Suchart As Sucharten
    Dim Ergebnis As Object

    ''' <summary>
    ''' 0=nicht indiziert (kein Hinkommen)   >0 -> x-1 =Bewegungskosten
    ''' </summary>
    ''' <remarks></remarks>
    Dim Spielfeld(,,) As Integer
    ''' <summary>
    ''' Das gleiche Spiel. Allerdings wird hier teilweise etwas aufgerundet. Wenn es beispielsweise eine (eigene) Einheit gibt. Dann kann dieses Feld, eben erst eine Runde später betreten werde.
    ''' </summary>
    ''' <remarks></remarks>
    Dim SpielfeldE(,,) As Integer
    ''' <summary>
    ''' Entsprechend Spielfeld, nur das hier nicht in Bewegungspunkten, sondern in Tage n gemessen wird. (wieder x-1=Tage)
    ''' </summary>
    ''' <remarks></remarks>
    Dim SpielfeldDiskret(,,) As Integer

    Dim Sucher As Stack(Of Wegsucher)

    Public Einheit As ObjektEinheit
    Dim MaxDauer As Integer
    Dim EinheitenIgnorieren As SuchartenEinheiten
    Dim StandardWetter As ObjektSpielfeld.Wetterarten


    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public WegpunkteX() As Integer = {}
    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public WegpunkteY() As Integer = {}
    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public WegpunkteSl() As Integer = {}

    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public sWegpunkteX As Stack(Of Integer) = New Stack(Of Integer)
    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public sWegpunkteY As Stack(Of Integer) = New Stack(Of Integer)
    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public sWegpunkteSl As Stack(Of Integer) = New Stack(Of Integer)
    ''' <summary>
    ''' Das Ziel Feld was man erreichen will!
    ''' </summary>
    ''' <remarks></remarks>
    Public ZielPunkt As Point
#End Region
#Region "Aufrufbare Routinen"
    ''' <summary>
    ''' Erstellt ein neues Wegsuchsystem für eine Einheit. Es wird gleich der Berechnungsstart aufgerufen, dieser muss also NICHT mehr aufgerufen werden.
    ''' </summary>
    ''' <param name="Einheit">Die Einheit für die das Wegsuchsystem erstellt wird. Es wird die Position von dieser Einheit benutzt.</param>
    ''' <param name="MaxDauer">evtl. eine Maximale dauer (Wegkosten, also NICHT Tage)</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Einheit As ObjektEinheit, Optional ByVal MaxDauer As Integer = -1, Optional ByVal SuchfeldAusbreiten As Boolean = True, Optional ByVal EinheitenIgnorieren As SuchartenEinheiten = SuchartenEinheiten.EinheitenBerücksichtigen)
        Feld = Objektverwalter.Spielfeld
        Sucher = New Stack(Of Wegsucher)
        Me.EinheitenIgnorieren = EinheitenIgnorieren

        BerechnungsStart(Einheit, MaxDauer, SuchfeldAusbreiten) 'Aus gründen der Kompatibilität, kann gleich der Berechnungsstart bei New ausgeführt werden.
    End Sub
    ''' <summary>
    ''' Erstellt ein neues Wegsuchsystem für eine Einheit. Es wird gleich der Berechnungsstart aufgerufen, dieser muss also NICHT mehr aufgerufen werden.
    ''' </summary>
    ''' <param name="Einheit">Die Einheit die benutzt wird, um die Wegkosten auszurechnen.</param>
    ''' <param name="PosX">Die Position, auf der die Einheit stehen soll, wenn sich das Wegsuchsystem ausbreitet.</param>
    ''' <param name="PosY">Die Position, auf der die Einheit stehen soll, wenn sich das Wegsuchsystem ausbreitet.</param>
    ''' <param name="Schlacht">Die Position, auf der die Einheit stehen soll, wenn sich das Wegsuchsystem ausbreitet.</param>
    ''' <param name="MaxDauer">evtl. eine Maximale dauer (Wegkosten, also NICHT Tage)</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Einheit As ObjektEinheit, ByVal PosX As Integer, ByVal PosY As Integer, ByVal Schlacht As Integer, Optional ByVal MaxDauer As Integer = -1, Optional ByVal SuchfeldAusbreiten As Boolean = True, Optional ByVal EinheitenIgnorieren As SuchartenEinheiten = SuchartenEinheiten.EinheitenBerücksichtigen)
        Feld = Objektverwalter.Spielfeld
        Sucher = New Stack(Of Wegsucher)
        Me.EinheitenIgnorieren = EinheitenIgnorieren

        BerechnungsStart(Einheit, PosX, PosY, Schlacht, MaxDauer, SuchfeldAusbreiten) 'Aus gründen der Kompatibilität, kann gleich der Berechnungsstart bei New ausgeführt werden.
    End Sub
    'Public Sub New(ByVal neuX As Integer, ByVal neuY As Integer, ByVal StartEinheit As ObjektEinheit, ByVal Schlacht As Integer)

    'End Sub

    ''' <summary>
    ''' Die Berechnung fängt an, sollte nur aufgerufen werden, wenn sie nicht bei New automatisch aufgerufen wurde.
    ''' </summary>
    ''' <param name="Einheit">Die Einheit für die das Wegsuchsystem erstellt wird. Es wird die Position von dieser Einheit benutzt.</param>
    ''' <param name="MaxDauer">evtl. eine Maximale dauer (Wegkosten, also NICHT Tage)</param>
    ''' <remarks></remarks>
    Public Sub BerechnungsStart(ByVal Einheit As ObjektEinheit, Optional ByVal MaxDauer As Integer = -1, Optional ByVal SuchfeldAusbreiten As Boolean = True)
        BerechnungsStart(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, MaxDauer, SuchfeldAusbreiten)
    End Sub
    ''' <summary>
    ''' Die Berechnung fängt an, sollte nur aufgerufen werden, wenn sie nicht bei New automatisch aufgerufen wurde.
    ''' </summary>
    ''' <param name="Einheit">Die Einheit die benutzt wird, um die Wegkosten auszurechnen.</param>
    ''' <param name="PosX">Die Position, auf der die Einheit stehen soll, wenn sich das Wegsuchsystem ausbreitet.</param>
    ''' <param name="PosY">Die Position, auf der die Einheit stehen soll, wenn sich das Wegsuchsystem ausbreitet.</param>
    ''' <param name="Schlacht">Die Position, auf der die Einheit stehen soll, wenn sich das Wegsuchsystem ausbreitet.</param>
    ''' <param name="MaxDauer">evtl. eine Maximale dauer (Wegkosten, also NICHT Tage)</param>
    ''' <remarks></remarks>
    Public Sub BerechnungsStart(ByVal Einheit As ObjektEinheit, ByVal PosX As Integer, ByVal PosY As Integer, ByVal Schlacht As Integer, Optional ByVal MaxDauer As Integer = -1, Optional ByVal bSuchfeldAusbreiten As Boolean = True)
        Me.Einheit = Einheit
        If MaxDauer = -1 Then
            Me.MaxDauer = -1
        Else
            Me.MaxDauer = MaxDauer + 1
        End If
        StandardWetter = Objektverwalter.Spielfeld.Regeln.Standardwetter
        ReDim Spielfeld(Feld.Breite - 1, Feld.Höhe - 1, 1) 'nachschauen, ob breite und höhe stimmt!
        ReDim SpielfeldE(Feld.Breite - 1, Feld.Höhe - 1, 1)
        ReDim SpielfeldDiskret(Feld.Breite - 1, Feld.Höhe - 1, 1)
        Sucher.Clear()
        If PosX >= 0 And PosY >= 0 Then
            setWegsucher(PosX, PosY, Schlacht, 1)
        End If
        Suchart = Sucharten.Normal
        If bSuchfeldAusbreiten Then SuchfeldAusbreiten()
    End Sub


    ''' <summary>
    ''' Macht ein bestimmtes Feld zum Ziel. Gibt True zurück, wenn das Feld erreicht werden kann!
    ''' </summary>
    ''' <param name="ZielKoordinateX"></param>
    ''' <param name="ZielKoordinateY"></param>
    ''' <param name="NebenFeldErreichbar">Wenn = False dann wird ein Feld nebendran gesucht. z.B.: Wenn das Zielfeld eine Gegnerische Einheit ist, dann will man ja nicht AUF, sondern NEBEN das Feld.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Ziel(ByVal ZielKoordinateX As Integer, ByVal ZielKoordinateY As Integer, ByVal NebenFeldErreichbar As Boolean) As Boolean
        Return Ziel(ZielKoordinateX, ZielKoordinateY, Einheit.GetMap, NebenFeldErreichbar)
    End Function
    ''' <summary>
    ''' Macht ein bestimmtes Feld zum Ziel. Gibt True zurück, wenn das Feld erreicht werden kann!
    ''' </summary>
    ''' <param name="ZielKoordinateX"></param>
    ''' <param name="ZielKoordinateY"></param>
    ''' <param name="NebenFeldErreichbar">Wenn = False dann wird ein Feld nebendran gesucht. z.B.: Wenn das Zielfeld eine Gegnerische Einheit ist, dann will man ja nicht AUF, sondern NEBEN das Feld.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Ziel(ByVal ZielKoordinateX As Integer, ByVal ZielKoordinateY As Integer, ByVal ZielKoordinateSchlacht As Integer, ByVal NebenFeldErreichbar As Boolean, Optional ByVal ZigZagZiel As Random = Nothing, Optional ByVal WegAbschneiden As Boolean = True) As Boolean
        'Zuerst wird der alte Weg gelöscht
        AltenWegLöschen()
        Dim ZielK(2) As Integer

        ZielK(0) = ZielKoordinateX
        ZielK(1) = ZielKoordinateY
        ZielK(2) = ZielKoordinateSchlacht
        If ZielK(2) = -1 Then ZielK(2) = Einheit.GetMap

        If NebenFeldErreichbar = False Then
            Dim Feld() As Integer = GetNebenFeld(ZielK(0), ZielK(1), ZielK(2))
            If Feld(0) >= 0 And Feld(1) >= 0 Then
                ZielK = Feld
            End If
        End If
        'Wenn der Ziel der Start ist, kann ich mir einiges Ersparen...
        If getBewegungspunktekosten(ZielK(0), ZielK(1), ZielK(2)) = 0 Then
            addEckpunkt(ZielK(0), ZielK(1), ZielK(2))
            WegpunkteUmwandeln()
            Return True
        End If
        'Prüft, ob das Ziel erreicht werden kann
        If getBewegungspunktekosten(ZielK(0), ZielK(1), ZielK(2)) < 0 Then
            Return False
        End If

        'Das Ziel ist erreichbar => Weg berechnen
        addEckpunkt(ZielK(0), ZielK(1), ZielK(2)) 'Das Ziel ist der letzte Wegpunkt.
        Dim Koo() As Integer = ZielK



        While getBewegungspunktekosten(Koo(0), Koo(1), Koo(2)) > 0 'Solange man noch etwas laufen muss..
            If Not IsNothing(ZigZagZiel) Then
                Koo = GetNebenFeldZufall(Koo(0), Koo(1), Koo(2), ZigZagZiel)
            Else
                Koo = GetNebenFeld(Koo(0), Koo(1), Koo(2))
            End If
            If Koo(0) >= 0 And Koo(1) >= 0 And Koo(2) >= 0 Then
                addEckpunkt(Koo(0), Koo(1), Koo(2))
            End If
        End While

        If WegAbschneiden Then
            If getRundeDiskret(getBewegungspunktekosten(ZielK(0), ZielK(1), ZielK(2)), False) > 0 Then
                'Oje soviel darf man aber nicht laufen, in diesem Fall müssen wir der KI noch den Weg kürzen.
                Dim sX As New Stack(Of Integer)
                Dim sY As New Stack(Of Integer)
                Dim sS As New Stack(Of Integer)
                While CanMoveOverField(sWegpunkteX.Peek, sWegpunkteY.Peek, sWegpunkteSl.Peek)
                    sX.Push(sWegpunkteX.Pop)
                    sY.Push(sWegpunkteY.Pop)
                    sS.Push(sWegpunkteSl.Pop)
                    If sWegpunkteX.Count <= 0 Then Exit While
                End While
                sWegpunkteX.Clear()
                sWegpunkteY.Clear()
                sWegpunkteSl.Clear()
                While sX.Count > 0
                    sWegpunkteX.Push(sX.Pop)
                    sWegpunkteY.Push(sY.Pop)
                    sWegpunkteSl.Push(sS.Pop)
                End While
            End If
        End If
        WegpunkteUmwandeln()
        Return True
    End Function

    Public Function Wegsuchen(ByVal FeindlEinheiten As Boolean) As Boolean
        'Wir suchen ein Feld von dem aus wir angreifen können bis ins unendliche
        'für Transport
        Suchart = Sucharten.FEinheit
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function
    Public Function Wegsuchen(ByVal Besetzung As Boolean, ByVal X As Integer) As Boolean
        'X ist nur zur unterscheidung von der oberen sub. Ansonsten suchen wir eine Besetzung
        'bis ins unendliche.
        'für Transport
        Suchart = Sucharten.Besetzung
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function
    Public Function Wegsuchen(ByVal X As Integer, ByVal Y As Integer) As Boolean
        'Können wir eine Besetzung in dieser Runde vom Feld X,Y aus erreichen?
        '???
        Dim KooX As Integer = X
        Dim KooY As Integer = Y
        Einheit.X = X
        Einheit.Y = Y
        Suchart = Sucharten.Besetzung
        MaxDauer = Einheit.GetMovementRange + 1
        SuchfeldAusbreiten()
        Einheit.X = KooX
        Einheit.Y = KooY
        Return Ergebnis
    End Function
    ''' <summary>
    ''' Gibt die Bewegungskostenzahl zurück, die gebraucht wird um das zielfeld zu erreichen.
    ''' </summary>
    ''' <param name="FeindlEinheiten"></param>
    ''' <param name="Besetzung"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Wegsuchen(ByVal FeindlEinheiten As Boolean, ByVal Besetzung As Boolean) As Integer
        'gibt zurück ob wir eine Feind oder eine Besetzung erreichen können und wie lange
        'Rückgabe Wie lange:-1 unerreichbar wir finden nichts
        If FeindlEinheiten = True And Besetzung = True Then
            Suchart = Sucharten.FEinheitBesetzung
        ElseIf FeindlEinheiten = True Then
            Suchart = Sucharten.FEinheitDaurRückgabe
        ElseIf Besetzung = True Then
            Suchart = Sucharten.BesetzungDauerRückgabe
        Else
            Suchart = Sucharten.Normal
        End If
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function
    ''' <summary>
    ''' Sucht bis zu einem Feind Besetzung virtuell und gibt das Zielfeld zurück!
    ''' </summary>
    ''' <param name="FeindlEinheiten"></param>
    ''' <param name="Besetzung"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function WegsuchenTransporter(ByVal FeindlEinheiten As Boolean, ByVal Besetzung As Boolean) As Point
        If FeindlEinheiten = True And Besetzung = True Then
            Suchart = Sucharten.TransportFEinheitBesetzung
        ElseIf FeindlEinheiten = True Then
            Suchart = Sucharten.TransportFEinheitDaurRückgabe
        ElseIf Besetzung = True Then
            Suchart = Sucharten.TransportBesetzungDauerRückgabe
        Else
            Suchart = Sucharten.Normal
        End If
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function
    ''' <summary>
    ''' Überprüft ob wir soweit laufen können
    ''' </summary>
    ''' <param name="BewPunkte"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function WegsuchenDauer(ByVal BewPunkte As Integer) As Boolean
        ZielPunkt.X = BewPunkte
        Suchart = Sucharten.Dauer
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function

    Public Function WegsuchenZiel(ByVal X As Integer, ByVal Y As Integer) As Boolean
        ZielPunkt = New Point(X, Y)
        Suchart = Sucharten.ZumZiel
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function
    ''' <summary>
    ''' Gibt die Bewegungskostenzahl zurück, die gebraucht wird um vom Gegner angegriffen zu werden.
    ''' Komische Funktion!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function WegsuchenBisGegenAngriff() As Integer
        'gibt zurück ob wir eine Feind oder eine Besetzung erreichen können und wie lange
        'Rückgabe Wie lange:-1 unerreichbar wir finden nichts
        Suchart = Sucharten.KannAngegriffenWerden
        SuchfeldAusbreiten()
        Return Ergebnis
    End Function

    Public Function getBewegungspunktekosten(ByVal WegPunkt As Integer) As Integer
        Return getBewegungspunktekosten(WegpunkteX(WegPunkt), WegpunkteY(WegPunkt), WegpunkteSl(WegPunkt))
    End Function
    Public Function getBewegungspunktekosten(ByVal P As Point) As Integer
        Return getBewegungspunktekosten(P.X, P.Y)
    End Function
    Public Function getBewegungspunktekosten(ByVal X As Integer, ByVal Y As Integer) As Integer
        Return getBewegungspunktekosten(X, Y, Einheit.GetMap)
    End Function
    Public Function getBewegungspunktekosten(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer) As Integer
        If Schlacht = -1 Then Return getBewegungspunktekosten(Schlacht, Y)
        If X >= 0 And Y >= 0 And X < Feld.Breite And Y < Feld.Höhe Then
            If Spielfeld(X, Y, Schlacht) > 0 Then
                If SpielfeldE(X, Y, Schlacht) > 0 Then
                    If Spielfeld(X, Y, Schlacht) - 1 = 0 Then
                        Return 0
                    Else
                        Return SpielfeldE(X, Y, Schlacht) - 1
                    End If
                Else
                    Return Spielfeld(X, Y, Schlacht) - 1
                End If
            Else
                Return -1
            End If
        Else
            Return -1
        End If
    End Function


    Public Function GetBewegungspunktekostenReal(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer) As Integer
        Return Spielfeld(X, Y, Schlacht) - 1
    End Function
    ''' <summary>
    ''' Löscht das Spielfeld für eine neu Berechnung und erstellt die Startpunkte neu!
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub NeueAusbreitung(ByVal MaxDauer As Integer)
        For I = 0 To 1
            For X = 0 To Feld.Breite - 1
                For Y = 0 To Feld.Höhe - 1
                    SpielfeldDiskret(X, Y, I) = 0
                    SpielfeldE(X, Y, I) = 0
                    If Spielfeld(X, Y, I) = 1 Then
                        Spielfeld(X, Y, I) = 0
                        setWegsucher(X, Y, I, 1)
                    Else
                        Spielfeld(X, Y, I) = 0
                    End If
                Next
            Next
        Next
        Ergebnis = Nothing
        ZielPunkt = Nothing
        Me.MaxDauer = MaxDauer
    End Sub

#End Region
#Region "Interne Routinen"
    Private Sub addEckpunkt(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer)
        sWegpunkteX.Push(X)
        sWegpunkteY.Push(Y)
        sWegpunkteSl.Push(Schlacht)
    End Sub

    ''' <summary>
    ''' Gibt das Nebenfeld mit den niedrigsten Bewegungskosten zurück. (-1|-1|-1) für nicht vorhanden. [Es wird das Feld bevorzugt, welches in richtung, der längeren achsenstrecke zum Start liegt.] noch nicht..
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetNebenFeld(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer) As Integer()
        Dim KooX As Integer = -1
        Dim KooY As Integer = -1
        Dim Sl As Integer = -1

        Dim Bew As Integer = Spielfeld(X, Y, Schlacht)
        If Objektverwalter.Spielfeld.OnMap(X + 1, Y) Then
            If Bew > Spielfeld(X + 1, Y, Schlacht) And Spielfeld(X + 1, Y, Schlacht) > 0 Then
                KooX = X + 1
                KooY = Y
                Sl = Schlacht
                Bew = Spielfeld(X + 1, Y, Schlacht)
            End If
        End If
        If Objektverwalter.Spielfeld.OnMap(X - 1, Y) Then
            If Bew > Spielfeld(X - 1, Y, Schlacht) And Spielfeld(X - 1, Y, Schlacht) > 0 Then
                KooX = X - 1
                KooY = Y
                Sl = Schlacht
                Bew = Spielfeld(X - 1, Y, Schlacht)
            End If
        End If
        If Objektverwalter.Spielfeld.OnMap(X, Y + 1) Then
            If Bew > Spielfeld(X, Y + 1, Schlacht) And Spielfeld(X, Y + 1, Schlacht) > 0 Then
                KooX = X
                KooY = Y + 1
                Sl = Schlacht
                Bew = Spielfeld(X, Y + 1, Schlacht)
            End If
        End If
        If Objektverwalter.Spielfeld.OnMap(X, Y - 1) Then
            If Bew > Spielfeld(X, Y - 1, Schlacht) And Spielfeld(X, Y - 1, Schlacht) > 0 Then
                KooX = X
                KooY = Y - 1
                Sl = Schlacht
                Bew = Spielfeld(X, Y - 1, Schlacht)
            End If
        End If
        Dim SchlN As Integer
        If Schlacht = 0 Then SchlN = 1 Else SchlN = 0
        If Bew > Spielfeld(X, Y, SchlN) And Spielfeld(X, Y, SchlN) > 0 Then
            KooX = X
            KooY = Y
            Sl = SchlN
            Bew = Spielfeld(X, Y, SchlN)
        End If
        Return New Integer() {KooX, KooY, Sl}
    End Function

    ''' <summary>
    ''' Gibt das Nebenfeld mit den niedrigsten Bewegungskosten zurück. (-1|-1|-1) für nicht vorhanden.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetNebenFeldZufall(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer, ByVal R As Random) As Integer()
        Dim KooX As Integer = -1
        Dim KooY As Integer = -1
        Dim Sl As Integer = -1

        Dim Bew As Integer = Spielfeld(X, Y, Schlacht)
        If Objektverwalter.Spielfeld.OnMap(X + 1, Y) Then
            If Bew > Spielfeld(X + 1, Y, Schlacht) And Spielfeld(X + 1, Y, Schlacht) > 0 Then
                KooX = X + 1
                KooY = Y
                Sl = Schlacht
                Bew = Spielfeld(X + 1, Y, Schlacht)
            End If
        End If
        If Objektverwalter.Spielfeld.OnMap(X - 1, Y) Then
            If Bew > Spielfeld(X - 1, Y, Schlacht) And Spielfeld(X - 1, Y, Schlacht) > 0 Then
                KooX = X - 1
                KooY = Y
                Sl = Schlacht
                Bew = Spielfeld(X - 1, Y, Schlacht)
            ElseIf Bew = Spielfeld(X - 1, Y, Schlacht) And Spielfeld(X - 1, Y, Schlacht) > 0 And R.Next(1, 100) <= 50 Then
                KooX = X - 1
                KooY = Y
                Sl = Schlacht
                Bew = Spielfeld(X - 1, Y, Schlacht)
            End If
        End If
        If Objektverwalter.Spielfeld.OnMap(X, Y + 1) Then
            If Bew > Spielfeld(X, Y + 1, Schlacht) And Spielfeld(X, Y + 1, Schlacht) > 0 Then
                KooX = X
                KooY = Y + 1
                Sl = Schlacht
                Bew = Spielfeld(X, Y + 1, Schlacht)
            ElseIf Bew = Spielfeld(X, Y + 1, Schlacht) And Spielfeld(X, Y + 1, Schlacht) > 0 And R.Next(1, 100) <= 50 Then
                KooX = X
                KooY = Y + 1
                Sl = Schlacht
                Bew = Spielfeld(X, Y + 1, Schlacht)
            End If
        End If
        If Objektverwalter.Spielfeld.OnMap(X, Y - 1) Then
            If Bew > Spielfeld(X, Y - 1, Schlacht) And Spielfeld(X, Y - 1, Schlacht) > 0 Then
                KooX = X
                KooY = Y - 1
                Sl = Schlacht
                Bew = Spielfeld(X, Y - 1, Schlacht)
            ElseIf Bew = Spielfeld(X, Y - 1, Schlacht) And Spielfeld(X, Y - 1, Schlacht) > 0 And R.Next(1, 100) <= 50 Then
                KooX = X
                KooY = Y - 1
                Sl = Schlacht
                Bew = Spielfeld(X, Y - 1, Schlacht)
            End If
        End If
        Dim SchlN As Integer
        If Schlacht = 0 Then SchlN = 1 Else SchlN = 0
        If Bew > Spielfeld(X, Y, SchlN) And Spielfeld(X, Y, SchlN) > 0 Then
            KooX = X
            KooY = Y
            Sl = SchlN
            Bew = Spielfeld(X, Y, SchlN)
        ElseIf Bew = Spielfeld(X, Y, SchlN) And Spielfeld(X, Y, SchlN) > 0 And R.Next(1, 100) <= 50 Then
            KooX = X
            KooY = Y
            Sl = SchlN
            Bew = Spielfeld(X, Y, SchlN)
        End If
        Return New Integer() {KooX, KooY, Sl}
    End Function

    Sub WegpunkteUmwandeln()
        WegpunkteX = sWegpunkteX.ToArray
        WegpunkteY = sWegpunkteY.ToArray
        WegpunkteSl = sWegpunkteSl.ToArray
        Array.Reverse(WegpunkteX)
        Array.Reverse(WegpunkteY)
        Array.Reverse(WegpunkteSl)
    End Sub
    Sub AltenWegLöschen()
        sWegpunkteX.Clear()
        sWegpunkteY.Clear()
        sWegpunkteSl.Clear()
    End Sub
    Sub SuchfeldAusbreiten(Optional ByVal Anfangsdauer As Integer = 1)
        Ergebnis = Nothing
        Do
            If SuchfeldAusbreitenAbbrechen(Anfangsdauer) Then
                Exit Do
            End If

            Dim alteSucher As Stack(Of Wegsucher) = Sucher
            Sucher = New Stack(Of Wegsucher)
            While alteSucher.Count > 0
                Dim S As Wegsucher = alteSucher.Pop
                If Spielfeld(S.KooX, S.KooY, S.Schlacht) <= Anfangsdauer Then
                    Dim Fertig As Boolean = True
                    WegsucherPlazieren(S.KooX + 1, S.KooY, S.Schlacht, Anfangsdauer, Fertig) 'Osten
                    WegsucherPlazieren(S.KooX - 1, S.KooY, S.Schlacht, Anfangsdauer, Fertig)  'Westen
                    WegsucherPlazieren(S.KooX, S.KooY + 1, S.Schlacht, Anfangsdauer, Fertig)  'Süden
                    WegsucherPlazieren(S.KooX, S.KooY - 1, S.Schlacht, Anfangsdauer, Fertig)  'Norden
                    If S.Schlacht = 0 Then
                        WegsucherPlazieren(S.KooX, S.KooY, S.Schlacht, Anfangsdauer, Fertig)   'Oben oder unten?
                    Else
                        WegsucherPlazieren(S.KooX, S.KooY, S.Schlacht, Anfangsdauer, Fertig)   'Oben oder unten?
                    End If
                    If Not Fertig Then
                        Sucher.Push(S) 'Der sucher ist noch nicht fertig
                    End If
                Else
                    'Der Wegsucher kommt erst später drann
                    Sucher.Push(S)
                End If
            End While
            Anfangsdauer += 1
        Loop
        'Dim strW As New IO.StreamWriter("C:\Zwischenablage\CW\WSS.txt", False)
        'strW.WriteLine(Environment.CommandLine)
        'strW.WriteLine()
        'For Y = 0 To Feld.Höhe - 1
        '    For x = 0 To Feld.Breite - 1
        '        Dim Punkte As String = Spielfeld(x, Y, 0)
        '        While Punkte.Length < 3
        '            Punkte = " " + Punkte
        '        End While
        '        strW.Write("|" + Punkte + "|")
        '    Next
        '    strW.WriteLine()
        'Next
        'strW.Close()

        'WegpunkteUmwandeln() 'Überflüssig?
        If Ergebnis Is Nothing Then
            Select Case Suchart
                Case Sucharten.Besetzung, Sucharten.FEinheit
                    Ergebnis = False
                Case Sucharten.FEinheitBesetzung
                    Ergebnis = -1
                Case Sucharten.KannAngegriffenWerden
                    Ergebnis = -1
                Case Sucharten.BesetzungDauerRückgabe
                    Ergebnis = -1
                Case Sucharten.FEinheitDaurRückgabe
                    Ergebnis = -1
                Case Sucharten.TransportBesetzungDauerRückgabe
                    Ergebnis = New Point(-1, -1)
                Case Sucharten.TransportFEinheitBesetzung
                    Ergebnis = New Point(-1, -1)
                Case Sucharten.TransportFEinheitDaurRückgabe
                    Ergebnis = New Point(-1, -1)
                Case Sucharten.ZumZiel
                    Ergebnis = False
                Case Sucharten.Dauer
                    Ergebnis = False
            End Select
        End If
    End Sub
    ''' <summary>
    ''' gibt zurück, ob das suchfeld ausbreiten abgebrochen werden soll. Es bricht das ausbreiten NICHT AB! es gibt nur zurück, ob es empfehlenswert ist!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function SuchfeldAusbreitenAbbrechen(ByVal aktuelleDauer As Integer) As Boolean
        If MaxDauer >= 0 Then
            If MaxDauer < aktuelleDauer Then Return True 'Wir steigen aus, wenn wir bis zum maximalen Zeitpunkt gesucht haben..
        End If
        If Not Sucher.Count > 0 Then Return True '..oder wir steigen aus, wenn es keine Wegsucher mehr gibt!

        If Ergebnis IsNot Nothing Then Return True

    End Function
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="Runde">0=Aktuelle Runde</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function getWetterauskunft(ByVal Runde As Integer) As ObjektSpielfeld.Wetterarten
        If Runde > 0 Then
            Return StandardWetter
        Else
            Return Feld.Regeln.Wetter
        End If
    End Function
    ''' <summary>
    ''' Die Aktuelle Runde = 0 ; Für SpielfeldDiskret muss man also noch 1 draufaddieren.
    ''' </summary>
    ''' <param name="Wegkosten">noch mit + 1</param>
    ''' <param name="WegK">wenn WegK=False, dann waren die Wegkosten vorhin ohne  + 1</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function getRundeDiskret(ByVal Wegkosten As Integer, Optional ByVal WegK As Boolean = True) As Integer
        Dim Runde As Integer
        Dim R As Integer
        Dim Bew As Integer = Einheit.GetMovementRange
        If Wegkosten < 0 Then
            Return -1
        ElseIf Bew = 0 Then
            If Wegkosten = 0 Then
                Return 0
            Else
                Return -1
            End If
        Else
            If WegK Then
                Runde = Math.DivRem(Wegkosten - 1, Bew, R)
            Else
                Runde = Math.DivRem(Wegkosten, Bew, R)
            End If
            If R = 0 Then
                Runde -= 1
                If Runde < 0 Then Runde = 0
            End If
        End If
        Return Runde
    End Function
    Function getNeueDauer(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer, ByRef Fertig As Boolean, ByVal Dauer As Integer) As Integer
        Dim Wegkosten As Integer = Objektverwalter.Bewegungskosten(Einheit, Feld.Landschaften(X, Y, Schlacht).getID, getWetterauskunft(getRundeDiskret(Dauer)), X, Y)
        If Not getRundeDiskret(Dauer) > 0 Then
            Dim E As ObjektEinheit = Feld.Einheiten(X, Y, Schlacht)
            If E IsNot Nothing Then
                If (EinheitenIgnorieren = SuchartenEinheiten.EinheitenBerücksichtigen) Or (EinheitenIgnorieren = SuchartenEinheiten.EigeneEinheitenIgnorieren) Or (EinheitenIgnorieren = SuchartenEinheiten.NichtGezogeneEinheitenIgnorieren And E.HatsichBewegt = True) Then
                    If E.GetSpieler.Team = Einheit.GetSpieler.Team Then
                        If Not (EinheitenIgnorieren = SuchartenEinheiten.EigeneEinheitenIgnorieren And Dauer + Wegkosten - 1 < Einheit.GetMovementRange) Then
                            'Freund
                            'Oje, das wird so ein vorläufiger Wegsucher...
                            If Wegkosten > 0 Then

                                If (E.IsLoadable(Einheit) And E.EntladungsUntergrund.Contains(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlacht).getID)) Then
                                    If Objektverwalter.Spielfeld.KI Is Nothing Or Objektverwalter.Spielfeld.AktuellerSpieler.KIStufe = ObjektSpieler.KIStufen.Passiv Then
                                        'Für Netzwerkspieler und Menschen ist das ein normales Feld.
                                    Else
                                        If Objektverwalter.Spielfeld.KI.KIModusIntern <> ObjektKI.KIModiIntern.TransporterVerladen Then
                                            If SpielfeldE(X, Y, Schlacht) = 0 Then
                                                SpielfeldE(X, Y, Schlacht) = (1 * Einheit.GetMovementRange) + Wegkosten + 1
                                            End If
                                        End If
                                    End If
                                ElseIf E.EinheitenID.ToUpper = Einheit.EinheitenID.ToUpper Then
                                    If Objektverwalter.Spielfeld.KI Is Nothing Or Objektverwalter.Spielfeld.AktuellerSpieler.KIStufe = ObjektSpieler.KIStufen.Passiv Then
                                        'Für Netzwerkspieler und Menschen ist das ein normales Feld.
                                    Else
                                        If Objektverwalter.Spielfeld.KI.KIModusIntern <> ObjektKI.KIModiIntern.Einen Then
                                            If SpielfeldE(X, Y, Schlacht) = 0 Then
                                                SpielfeldE(X, Y, Schlacht) = (1 * Einheit.GetMovementRange) + Wegkosten + 1
                                            End If
                                        Else
                                        End If
                                    End If
                                Else
                                    'Dann nicht in dieser Runde passierbar!
                                    If SpielfeldE(X, Y, Schlacht) = 0 Then
                                        SpielfeldE(X, Y, Schlacht) = (1 * Einheit.GetMovementRange) + Wegkosten + 1
                                    End If
                                End If
                            End If
                        End If
                    ElseIf Einheit.Bewegungsart = MovementSorts.Höllium.tostring Then
                        'Höllium läuft und macht alles platt. 
                    Else
                        'Feind
                        If E.isSichtbar(Einheit) Then
                            Fertig = False 'Warte noch etwas.
                            Return Nothing
                        End If
                    End If
                End If
            End If
        End If
        If Wegkosten < 0 Or Wegkosten > Einheit.GetMovementRange Then
            'Nicht passierbar... Generell, oder nur jetzt?
            If Objektverwalter.Bewegungskosten(Einheit, Feld.Landschaften(X, Y, Schlacht).getID, StandardWetter, X, Y) < 0 Or Objektverwalter.Bewegungskosten(Einheit, Feld.Landschaften(X, Y, Schlacht).getID, StandardWetter, X, Y) > Einheit.GetMovementRange Then
                'Wenn das immer so ist. Man muss auch einsehen können, wenn man wo nicht langgehen kann!
                Return -1 'nicht passierbar
            Else
                'Also nur ein Ausnahmefall
                Fertig = False
                Return Nothing
            End If
        End If
        If getRundeDiskret(Dauer + Wegkosten) > getRundeDiskret(Dauer) Then
            'die zwei Felder werden nicht in einer Runde passiert.
            Dauer = getRundeDiskret(Dauer + Wegkosten) * Einheit.GetMovementRange + 1
        End If
        Return Dauer + Wegkosten
    End Function
    Sub WegsucherPlazieren(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer, ByVal AlteDauer As Integer, ByRef Fertig As Boolean)
        If X < 0 Then Exit Sub
        If Y < 0 Then Exit Sub
        If X >= Feld.Breite Then Exit Sub
        If Y >= Feld.Höhe Then Exit Sub
        'Was ist die neue Dauer?
        Dim Fertig2 As Boolean = True
        Dim Dauer As Integer = getNeueDauer(X, Y, Schlacht, Fertig2, AlteDauer)
        'Da steht schon was drin!
        If Spielfeld(X, Y, Schlacht) <> 0 Then
            If Spielfeld(X, Y, Schlacht) > 0 Then
                'Wenn wir mehr brauchen als drin steht machen wir nichts ansonsten wird das überschrieben!
                If Dauer >= Spielfeld(X, Y, Schlacht) Then
                    CalculateErgebnis(X, Y, Schlacht)
                    Exit Sub
                End If
            Else
                Exit Sub
            End If
        End If

        'Zumindest der Rahmen wurde eingehalten.. Außerdem ist es noch nicht beschrieben.


        If Fertig2 Then
            setWegsucher(X, Y, Schlacht, Dauer)
        Else
            Fertig = False
        End If

    End Sub
    Sub setWegsucher(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer, ByVal Dauer As Integer)
        Spielfeld(X, Y, Schlacht) = Dauer
        If Dauer > 0 Then
            If CalculateErgebnis(X, Y, Schlacht) Then
                Exit Sub
            End If
        End If
        'SpielfeldDiskret
        If Dauer > 0 Then 'Andere Werte haben kein recht einen Wegsucher zu erschaffen. Wenn das Feld nicht passierbar ist, macht es keinen Sinn einen Wegsucher zu erschaffen!!!
            Sucher.Push(New Wegsucher(X, Y, Schlacht))
        End If
    End Sub
    Function CalculateErgebnis(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer) As Boolean
        Select Case Suchart
            Case Sucharten.FEinheit
                If CanAttack(X, Y, Schlacht, False) Then
                    Ergebnis = True
                    Return True
                End If
            Case Sucharten.Besetzung
                Dim G As ObjektGebäude = Feld.Landschaften(X, Y, Schlacht).Gebäude
                If G IsNot Nothing Then
                    If IsBesetzung(G, Schlacht) Then
                        Ergebnis = True
                        Return True
                    End If
                End If
            Case Sucharten.FEinheitBesetzung
                Dim G As ObjektGebäude = Feld.Landschaften(X, Y, Schlacht).Gebäude
                If G IsNot Nothing Then
                    If IsBesetzung(G, Schlacht) Then
                        Ergebnis = getBewegungspunktekosten(X, Y, Schlacht)
                        Return True
                    End If
                End If
                If CanAttack(X, Y, Schlacht, False) Then
                    '???Wie ist das mit Fernwaffen. Also mit dem Rückgabewert, an BewPunkten?
                    Ergebnis = getBewegungspunktekosten(X, Y, Schlacht)
                    Return True
                End If
            Case Sucharten.FEinheitDaurRückgabe
                If CanAttack(X, Y, Schlacht, False) Then
                    '???Wie ist das mit Fernwaffen. Also mit dem Rückgabewert, an BewPunkten?
                    Ergebnis = getBewegungspunktekosten(X, Y, Schlacht)
                    Return True
                End If
            Case Sucharten.BesetzungDauerRückgabe
                Dim G As ObjektGebäude = Feld.Landschaften(X, Y, Schlacht).Gebäude
                If G IsNot Nothing Then
                    If IsBesetzung(G, Schlacht) Then
                        Ergebnis = getBewegungspunktekosten(X, Y, Schlacht)
                        Return True
                    End If
                End If
            Case Sucharten.KannAngegriffenWerden
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team <> Einheit.GetSpieler.Team Then
                        If E.IsAttackable(Einheit, True, False) Then
                            Ergebnis = getBewegungspunktekosten(X, Y, Schlacht)
                            Return True
                        End If
                    End If
                End If
            Case Sucharten.TransportBesetzungDauerRückgabe
                Dim G As ObjektGebäude = Feld.Landschaften(X, Y, Schlacht).Gebäude
                If G IsNot Nothing Then
                    If IsBesetzung(G, Schlacht) Then
                        Ergebnis = New Point(X, Y)
                        Return True
                    End If
                End If
            Case Sucharten.TransportFEinheitBesetzung
                Dim G As ObjektGebäude = Feld.Landschaften(X, Y, Schlacht).Gebäude
                If G IsNot Nothing Then
                    If IsBesetzung(G, Schlacht) Then
                        Ergebnis = New Point(X, Y)
                        Return True
                    End If
                End If
                If CanAttack(X, Y, Schlacht, False) Then
                    '???Wie ist das mit Fernwaffen. Also mit dem Rückgabewert, an BewPunkten?
                    Ergebnis = New Point(X, Y)
                    Return True
                End If
            Case Sucharten.TransportFEinheitDaurRückgabe
                If CanAttack(X, Y, Schlacht, False) Then
                    '???Wie ist das mit Fernwaffen. Also mit dem Rückgabewert, an BewPunkten?
                    Ergebnis = New Point(X, Y)
                    Return True
                End If
            Case Sucharten.ZumZiel
                If X = ZielPunkt.X And Y = ZielPunkt.Y Then
                    Ergebnis = True
                    Return True
                End If
            Case Sucharten.Dauer
                If Spielfeld(X, Y, 0) >= ZielPunkt.X Then
                    Ergebnis = True
                    Return True
                End If
        End Select
        Return False
    End Function
    Function IsBesetzung(ByVal G As ObjektGebäude, ByVal Schlacht As Integer) As Boolean
        If G.IsBesetzung(Einheit) Then
            Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(G.Rechteck.X, G.Rechteck.Y, Schlacht)
            If E IsNot Nothing Then
                If Not (E.KannBesetzen And E.GetSpieler.Team = Einheit.GetSpieler.Team) Then
                    Return True
                End If
            Else
                Return True
            End If
        End If
        Return False
    End Function

    ''' <summary>
    ''' Gibt zurück, ob die Einheit von einer Position aus angreifen kann.
    ''' </summary>
    ''' <param name="X">Die Position der Einheit. Kann sie von dieser Position aus angreifen?</param>
    ''' <param name="Y">Die Position der Einheit. Kann sie von dieser Position aus angreifen?</param>
    ''' <param name="Schlacht">Die Position der Einheit. Kann sie von dieser Position aus angreifen?</param>
    ''' <param name="NahBew">Bei True: Wenn die Einheit eine Nahkampfeinheit ist, wird geschaut, ob sie angreifen kann, wenn sie sich noch bewegt! (noch nicht unterstützt)</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CanAttack(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer, ByVal NahBew As Boolean) As Boolean
        If Einheit.CanAttack() Then
            'immerhin hat die Einheit überhaupt Waffen!
            'Einheit.IsAttackable(
            'Einheit.MinimaleReichweite
            If Not Einheit.Waffe1.ToLower = "Keine".ToLower Then
                Dim L As ObjektLandschaft = Nothing
                L = getFeldRundrum(X, Y, Schlacht, 1, 1, L, Feld)
                Do Until L Is Nothing
                    If Einheit.IsAttackable(Feld.Einheiten(L.KooX, L.KooY, Schlacht), True) Then
                        Return True
                    End If
                    L = getFeldRundrum(X, Y, Schlacht, 1, 1, L, Feld)
                Loop
            End If
            If Not Einheit.Waffe2.ToLower = "keine" Then
                Dim L As ObjektLandschaft = Nothing
                L = getFeldRundrum(X, Y, Schlacht, Einheit.MinimaleReichweite, Einheit.MaximaleReichweite, L, Feld)
                Do Until L Is Nothing
                    If Einheit.IsAttackable(Feld.Einheiten(L.KooX, L.KooY, Schlacht), True) Then
                        Return True
                    End If
                    L = getFeldRundrum(X, Y, Schlacht, Einheit.MinimaleReichweite, Einheit.MaximaleReichweite, L, Feld)
                Loop
            End If
        End If
        Return False
    End Function
    Shared Function getFeldRundrum(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer, ByVal Min As Integer, ByVal Max As Integer, ByVal Landschaft As ObjektLandschaft, ByVal Feld As ObjektSpielfeld) As ObjektLandschaft
        Dim b As Boolean
        Dim OrgDis As Integer = 0
        If Landschaft Is Nothing Then
            b = True
        Else
            b = False
            OrgDis = getDistanzLuft(X, Y, Landschaft.KooX, Landschaft.KooY)
        End If
        If OrgDis < Min Then OrgDis = Min
        For MomentanterRadius = OrgDis To Max
            If MomentanterRadius > 0 Then
                Dim StartX As Integer = X
                Dim StartY As Integer = Y - MomentanterRadius
                For I = 1 To MomentanterRadius
                    StartX += 1
                    StartY += 1
                    If Feld.OnMap(StartX, StartY) Then
                        If b Then
                            Return Feld.Landschaften(StartX, StartY, Schlacht)
                        Else
                            If Landschaft.KooX = StartX Then
                                If Landschaft.KooY = StartY Then b = True
                            End If
                        End If
                    End If
                Next
                For I = 1 To MomentanterRadius
                    StartX -= 1
                    StartY += 1
                    If Feld.OnMap(StartX, StartY) Then
                        If b Then
                            Return Feld.Landschaften(StartX, StartY, Schlacht)
                        Else
                            If Landschaft.KooX = StartX Then
                                If Landschaft.KooY = StartY Then b = True
                            End If
                        End If
                    End If
                Next
                For I = 1 To MomentanterRadius
                    StartX -= 1
                    StartY -= 1
                    If Feld.OnMap(StartX, StartY) Then
                        If b Then
                            Return Feld.Landschaften(StartX, StartY, Schlacht)
                        Else
                            If Landschaft.KooX = StartX Then
                                If Landschaft.KooY = StartY Then b = True
                            End If
                        End If
                    End If
                Next
                For I = 1 To MomentanterRadius
                    StartX += 1
                    StartY -= 1
                    If Feld.OnMap(StartX, StartY) Then
                        If b Then
                            Return Feld.Landschaften(StartX, StartY, Schlacht)
                        Else
                            If Landschaft.KooX = StartX Then
                                If Landschaft.KooY = StartY Then b = True
                            End If
                        End If
                    End If
                Next
            Else
                If Feld.OnMap(X, Y) Then
                    If b Then
                        Return Feld.Landschaften(X, Y, Schlacht)
                    Else
                        If Landschaft.KooX = X Then
                            If Landschaft.KooY = Y Then b = True
                        End If
                    End If
                End If
            End If
        Next
        Return Nothing
        Return Feld.Landschaften(X, Y, Schlacht)
    End Function
    Shared Function getDistanzLuft(ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer) As Integer
        Dim deltaX As Integer = X1 - X2
        Dim deltaY As Integer = Y1 - Y2
        If deltaX < 0 Then deltaX *= -1
        If deltaY < 0 Then deltaY *= -1
        Return deltaX + deltaY
    End Function



    ''' <summary>
    ''' Können wir über das Feld drüber in dieser Runde.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Schlacht"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CanMoveOverField(ByVal X As Integer, ByVal Y As Integer, ByVal Schlacht As Integer) As Boolean
        If getRundeDiskret(getBewegungspunktekosten(X, Y, Schlacht), False) = 0 Then
            'Einfacher Fall
            Return True
        Else
            For I = 2 To sWegpunkteX.Count
                Dim NächstX As Integer = sWegpunkteX(sWegpunkteX.Count - I)
                Dim NächstY As Integer = sWegpunkteY(sWegpunkteY.Count - I)
                Dim NächstSchlacht As Integer = sWegpunkteSl(sWegpunkteSl.Count - I)
                If getRundeDiskret(getBewegungspunktekosten(NächstX, NächstY, NächstSchlacht), False) = 0 Then
                    Return True
                End If
            Next
        End If
        Return False
    End Function
#Region "Wegsucher"
    Private Class Wegsucher
        Public KooX As Integer
        Public KooY As Integer
        Public Schlacht As Integer
        Sub New(ByVal KooX As Integer, ByVal KooY As Integer, ByVal SchlachtInd As Integer)
            Me.KooX = KooX
            Me.KooY = KooY
            Schlacht = SchlachtInd
        End Sub
    End Class
#End Region
#End Region
End Class
















Public Class Wegsuchsystem_Alt
    Public StartX, StartY, ZielX, ZielY, DauerMax, Dauer As Integer
    Public Einheit As ObjektEinheit
    Dim Wegsucher() As Wegsucher = {}
    Dim Schlacht As Integer
    Public Suchfeld(,) As Integer
    Public TreibstoffMultiplikator As Integer = 1
    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public WegpunkteX() As Integer = {}
    ''' <summary>
    ''' Zuerst auf den Hintersten Punkt ziehen. Der erste Eckpunkt ist das Ziel! Der letzte Eckpunkt ist der Start!
    ''' </summary>
    ''' <remarks></remarks>
    Public WegpunkteY() As Integer = {}
    Dim WegpunktX As Integer, WegpunktY As Integer
    Dim Wegrichtung As String
    ''' <summary>
    ''' Benötigt zur Berechnung der Zugdauer.
    ''' </summary>
    ''' <remarks></remarks>
    Dim ZielPunkt As Point
    Dim Ini As Boolean = False
    ''' <summary>
    ''' Initialisiert das Objekt. Berechnet, alle Bewegungskosten. Anschließend muss "Ziel" ausgeführt werden
    ''' </summary>
    ''' <param name="StartEinheit"></param>
    ''' <param name="MaxDauer"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal StartEinheit As ObjektEinheit, ByVal neuX As Integer, ByVal neuY As Integer, ByVal Schlacht As Integer, Optional ByVal MaxDauer As Integer = -1)
        Einheit = StartEinheit
        StartX = neuX
        StartY = neuY
        DauerMax = MaxDauer
        Me.Schlacht = Schlacht
        'Das Suchfeld liegt überdem reelen Spielfeld der einHauptmenü.FeldbreiteRand ist nicht drinnen
        ReDim Suchfeld(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Höhe - 1)
        Dauer = NeueDauer(0, StartX, StartY) * (-1)
        'Alle nichtpassierbaren Landschaften & Felder mit Einheiten <> StartEinheit müssen auf -1 gesetzt werden.
        BlockierteFelderMarkieren(StartEinheit)

        Suchfeld(StartX, StartY) = Nothing
        addWegsucher(StartX, StartY, True)
        Ini = True
        Wegsuchen()
        'Jetzt steht in dem Suchfeld all die Zahlen, die die Bewegungskosten für das jeweilige Feld sind.  -Fehlerhaft-

    End Sub
    ''' <summary>
    ''' Lädt ein Wegsuchsystem für eine Transportersuche mit der KI
    ''' Darf nur von der KI aufgerufen werden. Danach muss Wegsuchen von der KI aufgerufen werden.
    ''' </summary>
    ''' <param name="neuX"></param>
    ''' <param name="neuY"></param>
    ''' <param name="StartEinheit"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal neuX As Integer, ByVal neuY As Integer, ByVal StartEinheit As ObjektEinheit, ByVal Schlacht As Integer)
        Einheit = StartEinheit
        StartX = neuX
        StartY = neuY
        DauerMax = -1
        Me.Schlacht = Schlacht
        'Das Suchfeld liegt überdem reelen Spielfeld der einHauptmenü.FeldbreiteRand ist nicht drinnen
        ReDim Suchfeld(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Höhe - 1)
        Dauer = NeueDauer(0, StartX, StartY) * (-1)
        'Alle nichtpassierbaren Landschaften & Felder mit Einheiten <> StartEinheit müssen auf -1 gesetzt werden.
        BlockierteFelderMarkieren(StartEinheit)
        Suchfeld(StartX, StartY) = Nothing
        addWegsucher(StartX, StartY, True)
        Ini = True
    End Sub


    Private Sub BlockierteFelderMarkieren(ByVal StartEinheit As ObjektEinheit)
        'Alle Blockierte Felder werden als unpassierbar Markiert
        For I = 0 To Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder.Count - 1
            If Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder(I).Z < 0 Then
                Suchfeld(Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder(I).X, Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder(I).Y) = -1
            End If
        Next
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                'Unpassierbare Landschaften
                If Objektverwalter.Bewegungskosten(Einheit, Objektverwalter.Spielfeld.Landschaften(X, Y, Schlacht).getID, Objektverwalter.Spielfeld.Regeln.Wetter, X, Y) = -1 Then Suchfeld(X, Y) = -1
                'Unpassierbare Einheit
                If Not IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht)) Then
                    If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Spieler).Team = Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).Team Then
                        If IsNothing(Objektverwalter.Spielfeld.KI) Then
                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Sichtbar = True Then
                                If Not StartEinheit.Bewegungsart = MovementSorts.Höllium.tostring Then
                                    Suchfeld(X, Y) = -1
                                End If
                            ElseIf Not Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KIStufe = ObjektSpieler.KIStufen.Mensch Then
                                Suchfeld(X, Y) = -1
                            End If
                        Else
                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Sichtbar = True Then
                                If Not StartEinheit.Bewegungsart = MovementSorts.Höllium.tostring Then
                                    Suchfeld(X, Y) = -1
                                End If
                            ElseIf Not Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KIStufe = ObjektSpieler.KIStufen.Mensch Then
                                Suchfeld(X, Y) = -1
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    Public Function GetBlockierteFelderMarkieren(ByVal StartEinheit As ObjektEinheit) As Integer(,)
        Dim SFeld(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Höhe - 1) As Integer
        'Alle Blockierte Felder werden als unpassierbar Markiert
        For I = 0 To Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder.Count - 1
            If Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder(I).Z < 0 Then
                SFeld(Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder(I).X, Objektverwalter.Spielfeld.Spieler(StartEinheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder(I).Y) = -1
            End If
        Next
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                'Unpassierbare Landschaften
                If Objektverwalter.Bewegungskosten(Einheit, Objektverwalter.Spielfeld.Landschaften(X, Y, Schlacht).getID, Objektverwalter.Spielfeld.Regeln.Wetter, X, Y) = -1 Then SFeld(X, Y) = -1
                'Unpassierbare Einheit
                If Not IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht)) Then
                    If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Spieler).Team = Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).Team Then
                        If IsNothing(Objektverwalter.Spielfeld.KI) Then
                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Sichtbar = True Then
                                If Not StartEinheit.Bewegungsart = MovementSorts.Höllium.tostring Then
                                    SFeld(X, Y) = -1
                                End If
                            ElseIf Not Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KIStufe = ObjektSpieler.KIStufen.Mensch Then
                                SFeld(X, Y) = -1
                            End If
                        Else
                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Sichtbar = True Then
                                If Not StartEinheit.Bewegungsart = MovementSorts.Höllium.tostring Then
                                    SFeld(X, Y) = -1
                                End If
                            ElseIf Not Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KIStufe = ObjektSpieler.KIStufen.Mensch Then
                                SFeld(X, Y) = -1
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return SFeld
    End Function
#Region "Ziel"
    ''' <summary>
    ''' Macht ein bestimmtes Feld zum Ziel. Gibt True zurück, wenn das Feld erreicht werden kann!
    ''' </summary>
    ''' <param name="ZielKoordinateX"></param>
    ''' <param name="ZielKoordinateY"></param>
    ''' <param name="NebenFeldErreichbar">Wenn = False dann wird ein Feld nebendran gesucht. z.B.: Wenn das Zielfeld eine Gegnerische Einheit ist, dann will man ja nicht AUF, sondern NEBEN das Feld.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Ziel(ByVal ZielKoordinateX As Integer, ByVal ZielKoordinateY As Integer, ByVal NebenFeldErreichbar As Boolean) As Boolean
        'Zuerst wird der alte Weg gelöscht
        AltenWegLöschen()

        ZielX = ZielKoordinateX
        ZielY = ZielKoordinateY
        If NebenFeldErreichbar = False Then
            Dim Feld() As Integer = GetNebenFeld(ZielX, ZielY)
            If Feld(0) >= 0 And Feld(1) >= 0 Then
                ZielX = Feld(0)
                ZielY = Feld(1)
            End If
        End If
        'Wenn der Ziel der Start ist, kann ich mir einiges Ersparen...
        If ZielX = StartX And ZielY = StartY Then
            addEckpunkt(ZielX, ZielY)
            Return True
        End If
        'Prüft, ob das Ziel erreicht werden kann
        If Suchfeld(ZielX, ZielY) <= 0 Then
            Return False
        End If
        'Das Ziel ist erreichbar => Weg berechnen
        Return Wegberechnen(True)

    End Function
    ''' <summary>
    ''' Die KI findet eine Einheit die weiter weg ist als ein Zug und will zu ihr hin laufen. Dass macht sie jetzt
    ''' </summary>
    ''' <param name="ZielKoordinateX"></param>
    ''' <param name="ZielKoordinateY"></param>
    ''' <param name="NebenFeldErreichbar"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Ziel(ByVal ZielKoordinateX As Integer, ByVal ZielKoordinateY As Integer, ByVal NebenFeldErreichbar As Boolean, ByVal Irgendwas As Integer) As Boolean
        'Zuerst wird der alte Weg gelöscht
        AltenWegLöschen()

        ZielX = ZielKoordinateX
        ZielY = ZielKoordinateY
        If NebenFeldErreichbar = False Then
            Dim Feld() As Integer = GetNebenFeld(ZielX, ZielY)
            If Feld(0) >= 0 And Feld(1) >= 0 Then
                ZielX = Feld(0)
                ZielY = Feld(1)
            End If
        End If
        'Wenn der Ziel der Start ist, kann ich mir einiges Ersparen...
        If ZielX = StartX And ZielY = StartY Then
            addEckpunkt(ZielX, ZielY)
            Return True
        End If
        'Prüft, ob das Ziel erreicht werden kann
        If Suchfeld(ZielX, ZielY) <= 0 Then
            Return False
        End If
        'Das Ziel ist erreichbar => Weg berechnen
        Dim Rückgabe As Boolean = Wegberechnen(True)
        'Wir finden heraus wie weit wir tatsächlich laufen dürfen.
        Dim WX() As Integer = {}
        Dim WY() As Integer = {}
        For I = 0 To WegpunkteX.Length - 1
            Dim Kosten As Integer = getBewegungspunktekosten(WegpunkteX(I), WegpunkteY(I))
            If Kosten > Einheit.GetMovementRange And Kosten >= 0 Then

            Else
                Array.Resize(WX, WX.Length + 1)
                Array.Resize(WY, WY.Length + 1)
                WX(WX.Length - 1) = WegpunkteX(I)
                WY(WY.Length - 1) = WegpunkteY(I)
            End If
        Next

        'so jetzt müssen wir noch dafür sorgen, dass die Einheit nicht ausversehen auf einer anderen zum stehen kommt.
        If ObjektKI.IsFeldLeer(WX(0), WY(0), Einheit) = True Then
            WegpunkteX = WX
            WegpunkteY = WY
        ElseIf Objektverwalter.Spielfeld.Einheiten(WX(0), WY(0), Schlacht).IsLoadable(Einheit) = True And Objektverwalter.Spielfeld.KI.KIModusEinheitenBefehl = ObjektKI.KIModiExtern.Fracht Then
            'Wir wollen auf dieses Feld weil wir eine Einheit laden wollen
            WegpunkteX = WX
            WegpunkteY = WY
        ElseIf Einheit.Bewegungsart = MovementSorts.Höllium.tostring And Objektverwalter.Spielfeld.Einheiten(WX(0), WY(0), Schlacht).IsEnemy(Einheit) = True Then
            'Hölliums können über Gegner laufen.
            WegpunkteX = WX
            WegpunkteY = WY
        Else
            Select Case Objektverwalter.Spielfeld.AktuellerSpieler.KIStufe
                'Einfache KI's reihen ihre Einheiten in einer Reihe auf. Doof aber wir sind ja auch einfach.=)
                Case Is <= ObjektSpieler.KIStufen.Einfach
                    For I = 0 To WX.Length - 1
                        If ObjektKI.IsFeldLeer(WX(I), WY(I), Einheit) = True Then
                            Array.Resize(WegpunkteX, WX.Length - I)
                            Array.Resize(WegpunkteY, WY.Length - I)
                            For I2 = I To WX.Length - 1
                                WegpunkteX(I2 - I) = WX(I2)
                                WegpunkteY(I2 - I) = WY(I2)
                            Next
                            Exit For
                        End If
                    Next
                Case Is >= ObjektSpieler.KIStufen.Normal < 5
                    'Das hier gehört noch optimiert und korriegiert.
                    For I = 0 To WX.Length - 1
                        Dim P As Point = GetAngrenzendesfreiesFeld(WX(I), WY(I))
                        If P.X >= 0 Then
                            If P.X <> WX(0) Or P.Y <> WY(0) Then
                                Ziel(P.X, P.Y, True)
                                Exit For
                            End If
                        End If
                    Next
                Case Else

            End Select
        End If

        'Sie könnte gar nicht laufen dann bleibt sie stehen.
        If WegpunkteX.Length <= 0 Then
            Array.Resize(WegpunkteX, 1)
            Array.Resize(WegpunkteY, 1)
            WegpunkteX(0) = StartX
            WegpunkteY(0) = StartY
        End If
        Return Rückgabe
    End Function
    Public Function ZigZagZiel(ByVal ZielKoordinateX As Integer, ByVal ZielKoordinateY As Integer, ByVal NebenFeldErreichbar As Boolean) As Boolean
        'Zuerst wird der alte Weg gelöscht
        AltenWegLöschen()

        ZielX = ZielKoordinateX
        ZielY = ZielKoordinateY
        If NebenFeldErreichbar = False Then
            Dim Feld() As Integer = GetNebenFeld(ZielX, ZielY)
            If Feld(0) >= 0 And Feld(1) >= 0 Then
                ZielX = Feld(0)
                ZielY = Feld(1)
            End If
        End If
        'Wenn der Ziel der Start ist, kann ich mir einiges Ersparen...
        If ZielX = StartX And ZielY = StartY Then
            addEckpunkt(ZielX, ZielY)
            Return True
        End If
        'Prüft, ob das Ziel erreicht werden kann
        If Suchfeld(ZielX, ZielY) <= 0 Then
            Return False
        End If
        'Das Ziel ist erreichbar => Weg berechnen
        Return Wegberechnen2(True)
    End Function
    Public Function GetAngrenzendesfreiesFeld(ByVal X As Integer, ByVal Y As Integer) As Point

        If ObjektKI.IsFeldLeer(X, Y, Einheit) Then
            Return New Point(X, Y)
        Else
            Dim X2 As Integer = X
            Dim Y2 As Integer = Y
            For I = 0 To 3
                Select Case I
                    Case 0
                        X2 -= 1
                    Case 1
                        X2 += 1
                        Y2 -= 1
                    Case 2
                        X2 += 1
                        Y2 += 1
                    Case 3
                        X2 -= 1
                        Y2 += 1
                End Select
                If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                    If ObjektKI.IsFeldLeer(X2, Y2, Einheit) Then
                        Dim Bew As Integer = getBewegungspunktekosten(X2, Y2)
                        If Bew <= Einheit.GetMovementRange And Bew >= 0 Then
                            Return New Point(X2, Y2)
                        End If
                    End If
                End If
            Next
            Return New Point(-1, -1)
        End If
    End Function
    Private Function IsWegpunkt(ByVal X As Integer, ByVal Y As Integer) As Boolean
        For I = 0 To WegpunkteX.Length - 1
            If WegpunkteX(I) = X Then
                If WegpunkteY(I) = Y Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
#End Region
    ''' <summary>
    ''' Gibt das Neben Feld mit den niedrigsten Bewegungskosten zurück
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetNebenFeld(ByVal X As Integer, ByVal Y As Integer) As Integer()
        Dim NebenFeld() As Integer = {-1, -1}
        Dim Kreis(,) As Integer = Kreisfunktion(1)
        Dim WegkostenAlt As Integer = 99999999
        For I = 0 To 2
            For I2 = 0 To 2
                If Kreis(I, I2) = 1 Then
                    If X - 1 + I >= 0 And Y - 1 + I2 >= 0 And X - 1 + I < Suchfeld.GetLength(0) And Y - 1 + I2 < Suchfeld.GetLength(1) Then
                        Dim Wegkostenneu As Integer = getBewegungspunktekosten(X - 1 + I, Y - 1 + I2)
                        If Wegkostenneu >= 0 Then
                            If Wegkostenneu < WegkostenAlt Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - 1 + I, Y - 1 + I2, Schlacht)) Then
                                    WegkostenAlt = Wegkostenneu
                                    NebenFeld(0) = X - 1 + I
                                    NebenFeld(1) = Y - 1 + I2
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return NebenFeld
    End Function
    ''' <summary>
    ''' Gibt das näheste Feld zurück von dem aus das angegebene Feld bombardiert werden kann
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetNähestestAngriffsFeld(ByVal X As Integer, ByVal Y As Integer) As Integer()
        Dim Feld() As Integer = {-1, -1}
        Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
        Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
        Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
        Dim WegkostenAlt As Integer = 99999999
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Kreis(X1, Y1) >= MinimaleReichweite Then
                    If Kreis(X1, Y1) <= MaximaleReichweite Then
                        If X - 1 + X1 >= 0 And Y - 1 + Y1 >= 0 And X - 1 + X1 < Suchfeld.GetLength(0) And Y - 1 + Y1 < Suchfeld.GetLength(1) Then
                            If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - 1 + X1, Y - 1 + Y1, Schlacht)) Then
                                Dim Wegkostenneu As Integer = getBewegungspunktekosten(X - 1 + X1, Y - 1 + Y1)
                                If Wegkostenneu >= 0 Then
                                    If Wegkostenneu < WegkostenAlt Then
                                        WegkostenAlt = Wegkostenneu
                                        Feld(0) = X - 1 + X1
                                        Feld(1) = Y - 1 + Y1
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Feld
    End Function
    Private Function Wegberechnen(ByVal NebenFeld As Boolean) As Boolean
        'Vom Ziel ausgehend immer auf das niedrigste benachbarte Feld springen
        WegpunktX = ZielX
        WegpunktY = ZielY
        Dim XORY As Integer = Zufallszahl(0, 1)
        If NebenFeld = True Then addEckpunkt(ZielX, ZielY)
        While Not (WegpunktX = StartX And WegpunktY = StartY)
            If XORY = 1 Then
                kleinsterNachbar()
            Else
                kleinsterNachbar2()
            End If

            addEckpunkt(WegpunktX, WegpunktY)
        End While
        Return True
    End Function
    Public Sub AltenWegLöschen()
        Array.Resize(WegpunkteX, 0)
        Array.Resize(WegpunkteY, 0)
    End Sub
    Private Function Wegberechnen2(ByVal NebenFeld As Boolean) As Boolean
        'Vom Ziel ausgehend immer auf das niedrigste benachbarte Feld springen
        WegpunktX = ZielX
        WegpunktY = ZielY
        If NebenFeld = True Then addEckpunkt(ZielX, ZielY)
        While Not (WegpunktX = StartX And WegpunktY = StartY)
            If Zufallszahl(0, 1) = 1 Then
                kleinsterNachbar()
            Else
                kleinsterNachbar2()
            End If

            addEckpunkt(WegpunktX, WegpunktY)
        End While
        Return True
    End Function

    Private Sub kleinsterNachbar()
        Dim WegpunktXNeu As Integer = WegpunktX
        Dim WegpunktYNeu As Integer = WegpunktY
        Dim kli As Integer = 99999999
        'Diese 4 Fälle sind bei allen Feldern gleich
        If WegpunktY - 1 >= 0 Then
            If kli > Suchfeld(WegpunktX, WegpunktY - 1) And Suchfeld(WegpunktX, WegpunktY - 1) > 0 Then
                kli = Suchfeld(WegpunktX, WegpunktY - 1)
                WegpunktXNeu = WegpunktX
                WegpunktYNeu = WegpunktY - 1
            ElseIf WegpunktX = StartX And WegpunktY - 1 = StartY Then
                WegpunktY -= 1
                Exit Sub
            End If
        End If
        If WegpunktY + 1 < Objektverwalter.Spielfeld.Höhe Then
            If kli > Suchfeld(WegpunktX, WegpunktY + 1) And Suchfeld(WegpunktX, WegpunktY + 1) > 0 Then
                kli = Suchfeld(WegpunktX, WegpunktY + 1)
                WegpunktXNeu = WegpunktX
                WegpunktYNeu = WegpunktY + 1
            ElseIf WegpunktX = StartX And WegpunktY + 1 = StartY Then
                WegpunktY += 1
                Exit Sub
            End If
        End If
        If WegpunktX - 1 >= 0 Then
            If kli > Suchfeld(WegpunktX - 1, WegpunktY) And Suchfeld(WegpunktX - 1, WegpunktY) > 0 Then
                kli = Suchfeld(WegpunktX - 1, WegpunktY)
                WegpunktXNeu = WegpunktX - 1
                WegpunktYNeu = WegpunktY
            ElseIf WegpunktX - 1 = StartX And WegpunktY = StartY Then
                WegpunktX -= 1
                Exit Sub
            End If
        End If
        If WegpunktX + 1 < Objektverwalter.Spielfeld.Breite Then
            If kli > Suchfeld(WegpunktX + 1, WegpunktY) And Suchfeld(WegpunktX + 1, WegpunktY) > 0 Then
                kli = Suchfeld(WegpunktX + 1, WegpunktY)
                WegpunktXNeu = WegpunktX + 1
                WegpunktYNeu = WegpunktY
            ElseIf WegpunktX + 1 = StartX And WegpunktY = StartY Then
                WegpunktX += 1
                Exit Sub
            End If
        End If
        WegpunktX = WegpunktXNeu
        WegpunktY = WegpunktYNeu
    End Sub
    Private Sub kleinsterNachbar2()
        Dim WegpunktXNeu As Integer = WegpunktX
        Dim WegpunktYNeu As Integer = WegpunktY
        Dim kli As Integer = 99999999
        'Diese 4 Fälle sind bei allen Feldern gleich
        If WegpunktX - 1 >= 0 Then
            If kli > Suchfeld(WegpunktX - 1, WegpunktY) And Suchfeld(WegpunktX - 1, WegpunktY) > 0 Then
                kli = Suchfeld(WegpunktX - 1, WegpunktY)
                WegpunktXNeu = WegpunktX - 1
                WegpunktYNeu = WegpunktY
            ElseIf WegpunktX - 1 = StartX And WegpunktY = StartY Then
                WegpunktX -= 1
                Exit Sub
            End If
        End If
        If WegpunktX + 1 < Objektverwalter.Spielfeld.Breite Then
            If kli > Suchfeld(WegpunktX + 1, WegpunktY) And Suchfeld(WegpunktX + 1, WegpunktY) > 0 Then
                kli = Suchfeld(WegpunktX + 1, WegpunktY)
                WegpunktXNeu = WegpunktX + 1
                WegpunktYNeu = WegpunktY
            ElseIf WegpunktX + 1 = StartX And WegpunktY = StartY Then
                WegpunktX += 1
                Exit Sub
            End If
        End If
        If WegpunktY - 1 >= 0 Then
            If kli > Suchfeld(WegpunktX, WegpunktY - 1) And Suchfeld(WegpunktX, WegpunktY - 1) > 0 Then
                kli = Suchfeld(WegpunktX, WegpunktY - 1)
                WegpunktXNeu = WegpunktX
                WegpunktYNeu = WegpunktY - 1
            ElseIf WegpunktX = StartX And WegpunktY - 1 = StartY Then
                WegpunktY -= 1
                Exit Sub
            End If
        End If
        If WegpunktY + 1 < Objektverwalter.Spielfeld.Höhe Then
            If kli > Suchfeld(WegpunktX, WegpunktY + 1) And Suchfeld(WegpunktX, WegpunktY + 1) > 0 Then
                kli = Suchfeld(WegpunktX, WegpunktY + 1)
                WegpunktXNeu = WegpunktX
                WegpunktYNeu = WegpunktY + 1
            ElseIf WegpunktX = StartX And WegpunktY + 1 = StartY Then
                WegpunktY += 1
                Exit Sub
            End If
        End If
        WegpunktX = WegpunktXNeu
        WegpunktY = WegpunktYNeu
    End Sub
    Private Sub addEckpunkt(ByVal X As Integer, ByVal Y As Integer)
        Array.Resize(WegpunkteX, WegpunkteX.Length + 1)
        Array.Resize(WegpunkteY, WegpunkteX.Length)
        WegpunkteX(WegpunkteX.Length - 1) = X
        WegpunkteY(WegpunkteY.Length - 1) = Y
    End Sub

    Private Sub Wegsuchen()
        Do
            If Not DauerMax = -1 Then
                If Dauer >= DauerMax Then
                    Exit Sub
                End If
            End If
            Dauer += 1
            Dim alteWegsucher(Wegsucher.Length - 1) As Wegsucher
            For I As Integer = 0 To Wegsucher.Length - 1
                alteWegsucher(I) = Wegsucher(I)
            Next
            Array.Resize(Wegsucher, 0)
            For I As Integer = 0 To alteWegsucher.Length - 1
                If Dauer >= alteWegsucher(I).getDauer Then
                    'Diese 4 Fälle sind bei allen Feldern gleich
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY - 1)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY + 1)
                    addWegsucher(alteWegsucher(I).getX + 1, alteWegsucher(I).getY)
                    addWegsucher(alteWegsucher(I).getX - 1, alteWegsucher(I).getY)
                Else
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY, alteWegsucher(I).getDauer)
                End If
            Next
        Loop While Wegsucher.Length > 0
    End Sub
    ''' <summary>
    ''' Gibt zurück ob von einem Feld aus ein solches Ziel erreicht werden kann.
    ''' </summary>
    ''' <param name="FeindlEinheiten"></param>
    ''' <param name="Besetzung"></param>
    ''' <param name="Transporter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Wegsuchen(ByVal FeindlEinheiten As Boolean, ByVal Besetzung As Boolean, ByVal Transporter As Boolean) As Boolean
        Dim Rückgabe As Boolean = False
        Do
            If Not DauerMax = -1 Then
                If Dauer >= DauerMax Then
                    Exit Function
                End If
            End If
            Dauer += 1
            Dim alteWegsucher(Wegsucher.Length - 1) As Wegsucher
            For I As Integer = 0 To Wegsucher.Length - 1
                alteWegsucher(I) = Wegsucher(I)
            Next
            Array.Resize(Wegsucher, 0)
            For I As Integer = 0 To alteWegsucher.Length - 1
                If Dauer >= alteWegsucher(I).getDauer Then
                    'Diese 4 Fälle sind bei allen Feldern gleich
                    Rückgabe = CheckAngrenzendeFelder(alteWegsucher(I).getX, alteWegsucher(I).getY, FeindlEinheiten, Besetzung, Transporter)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY - 1)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY + 1)
                    addWegsucher(alteWegsucher(I).getX + 1, alteWegsucher(I).getY)
                    addWegsucher(alteWegsucher(I).getX - 1, alteWegsucher(I).getY)
                Else
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY, alteWegsucher(I).getDauer)
                End If
            Next
        Loop While Wegsucher.Length > 0 And Rückgabe = False
        Return Rückgabe
    End Function
    ''' <summary>
    ''' Gibt zurück wie lange wir brauchen um ein bestimmtes Ziel zu erreichen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Wegsuchen(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim Rückgabe As Boolean = False
        Do
            If Not DauerMax = -1 Then
                If Dauer >= DauerMax Then
                    Exit Function
                End If
            End If
            Dauer += 1
            Dim alteWegsucher(Wegsucher.Length - 1) As Wegsucher
            For I As Integer = 0 To Wegsucher.Length - 1
                alteWegsucher(I) = Wegsucher(I)
            Next
            Array.Resize(Wegsucher, 0)
            For I As Integer = 0 To alteWegsucher.Length - 1
                If Dauer >= alteWegsucher(I).getDauer Then
                    'Diese 4 Fälle sind bei allen Feldern gleich
                    Rückgabe = CheckAngrenzendeFelder(alteWegsucher(I).getX, alteWegsucher(I).getY, False, True)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY - 1)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY + 1)
                    addWegsucher(alteWegsucher(I).getX + 1, alteWegsucher(I).getY)
                    addWegsucher(alteWegsucher(I).getX - 1, alteWegsucher(I).getY)
                Else
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY, alteWegsucher(I).getDauer)
                End If
            Next
        Loop While Wegsucher.Length > 0 And Rückgabe = False And Dauer < Einheit.GetMovementRange
        If Rückgabe = True Then
            If getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) <= Einheit.GetMovementRange Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt zurück ob von einem Feld aus ein solches Ziel erreicht werden kann.
    ''' </summary>
    ''' <param name="FeindlEinheiten"></param>
    ''' <param name="Besetzung"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Wegsuchen(ByVal FeindlEinheiten As Boolean, ByVal Besetzung As Boolean) As Integer
        Dim Rückgabe As Boolean = False
        ZielPunkt = New Point(-1, -1)
        Do
            If Not DauerMax = -1 Then
                If Dauer >= DauerMax Then
                    Exit Function
                End If
            End If
            Dauer += 1
            Dim alteWegsucher(Wegsucher.Length - 1) As Wegsucher
            For I As Integer = 0 To Wegsucher.Length - 1
                alteWegsucher(I) = Wegsucher(I)
            Next
            Array.Resize(Wegsucher, 0)
            For I As Integer = 0 To alteWegsucher.Length - 1
                If Dauer >= alteWegsucher(I).getDauer Then
                    'Diese 4 Fälle sind bei allen Feldern gleich
                    Rückgabe = CheckAngrenzendeFelder(alteWegsucher(I).getX, alteWegsucher(I).getY, FeindlEinheiten, Besetzung)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY - 1)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY + 1)
                    addWegsucher(alteWegsucher(I).getX + 1, alteWegsucher(I).getY)
                    addWegsucher(alteWegsucher(I).getX - 1, alteWegsucher(I).getY)
                Else
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY, alteWegsucher(I).getDauer)
                End If
            Next
        Loop While Wegsucher.Length > 0 And Rückgabe = False
        Return getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y)
    End Function
    ''' <summary>
    ''' Gibt zurück ob von einem Feld aus ein solches Ziel erreicht werden kann.
    ''' </summary>
    ''' <param name="FeindlEinheiten"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Wegsuchen(ByVal FeindlEinheiten As Boolean) As Boolean
        Dim Rückgabe As Boolean = False
        Do
            If Not DauerMax = -1 Then
                If Dauer >= DauerMax Then
                    Exit Function
                End If
            End If
            Dauer += 1
            Dim alteWegsucher(Wegsucher.Length - 1) As Wegsucher
            For I As Integer = 0 To Wegsucher.Length - 1
                alteWegsucher(I) = Wegsucher(I)
            Next
            Array.Resize(Wegsucher, 0)
            For I As Integer = 0 To alteWegsucher.Length - 1
                If Dauer >= alteWegsucher(I).getDauer Then
                    'Diese 4 Fälle sind bei allen Feldern gleich
                    Dim R2 As Boolean = CheckAngrenzendeFelder(alteWegsucher(I).getX, alteWegsucher(I).getY, FeindlEinheiten, False)
                    If Rückgabe = False And R2 = True Then
                        Rückgabe = True
                    End If
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY - 1)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY + 1)
                    addWegsucher(alteWegsucher(I).getX + 1, alteWegsucher(I).getY)
                    addWegsucher(alteWegsucher(I).getX - 1, alteWegsucher(I).getY)
                Else
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY, alteWegsucher(I).getDauer)
                End If
            Next
        Loop While Wegsucher.Length > 0
        Return Rückgabe
    End Function
    ''' <summary>
    ''' Gibt zurück ob von einem Feld aus ein solches Ziel erreicht werden kann.
    ''' </summary>
    ''' <param name="Besetzung"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Wegsuchen(ByVal Besetzung As Boolean, ByVal X As Integer) As Boolean
        Dim Rückgabe As Boolean = False
        Do
            If Not DauerMax = -1 Then
                If Dauer >= DauerMax Then
                    Exit Function
                End If
            End If
            Dauer += 1
            Dim alteWegsucher(Wegsucher.Length - 1) As Wegsucher
            For I As Integer = 0 To Wegsucher.Length - 1
                alteWegsucher(I) = Wegsucher(I)
            Next
            Array.Resize(Wegsucher, 0)
            For I As Integer = 0 To alteWegsucher.Length - 1
                If Dauer >= alteWegsucher(I).getDauer Then
                    'Diese 4 Fälle sind bei allen Feldern gleich
                    Dim R2 As Boolean = CheckAngrenzendeFelder(alteWegsucher(I).getX, alteWegsucher(I).getY, False, True)
                    If Rückgabe = False And R2 = True Then
                        Rückgabe = True
                    End If
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY - 1)
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY + 1)
                    addWegsucher(alteWegsucher(I).getX + 1, alteWegsucher(I).getY)
                    addWegsucher(alteWegsucher(I).getX - 1, alteWegsucher(I).getY)
                Else
                    addWegsucher(alteWegsucher(I).getX, alteWegsucher(I).getY, alteWegsucher(I).getDauer)
                End If
            Next
        Loop While Wegsucher.Length > 0
        Return Rückgabe
    End Function


    ''' <summary>
    ''' Wir schauen ob eines der angrenzenden Felder eines unserer Ziele ist.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="FeindlEinheiten"></param>
    ''' <param name="Besetzung"></param>
    ''' <param name="Transporter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CheckAngrenzendeFelder(ByVal X As Integer, ByVal Y As Integer, ByVal FeindlEinheiten As Boolean, ByVal Besetzung As Boolean, ByVal Transporter As Boolean) As Boolean
        Dim Rückgabe As Boolean = False
        Dim X2 As Integer = X
        Dim Y2 As Integer = Y
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If Objektverwalter.Spielfeld.OnMap(X2, Y2) = True Then
                If FeindlEinheiten = True Then
                    If KannFernkampfGemachtWerden(Einheit, X2, Y2) Then
                        If Rückgabe = False Then
                            Rückgabe = True
                            ZielPunkt = New Point(X2, Y2)
                        ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                            ZielPunkt = New Point(X2, Y2)
                        End If
                    End If
                    If KannNahkampfvonFeldgemachtwerden(Einheit, X2, Y2) = True Then
                        If Rückgabe = False Then
                            Rückgabe = True
                            ZielPunkt = New Point(X2, Y2)
                        ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                            ZielPunkt = New Point(X2, Y2)
                        End If
                    End If
                End If
                If Transporter = True Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlacht)
                    If Not E Is Nothing Then
                        If E.IsLoadable(Einheit) = True Then
                            If Rückgabe = False Then
                                Rückgabe = True
                                ZielPunkt = New Point(X2, Y2)
                            ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                                ZielPunkt = New Point(X2, Y2)
                            End If
                        End If
                    End If
                End If
                If Besetzung = True Then
                    If Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlacht) Is Nothing Then
                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X2, Y2, Schlacht).Gebäude
                        If Not G Is Nothing Then
                            If G.IsBesetzung(Einheit.Spieler) = True Then
                                If Rückgabe = False Then
                                    Rückgabe = True
                                    ZielPunkt = New Point(X2, Y2)
                                ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                                    ZielPunkt = New Point(X2, Y2)
                                End If
                            End If
                        End If
                    End If
                End If
                addWegsucher(X2, Y2, )
            End If
        Next
        Return Rückgabe
    End Function
    ''' <summary>
    ''' Wir schauen ob eines der angrenzenden Felder eines unserer Ziele ist.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="FeindlEinheiten"></param>
    ''' <param name="Besetzung"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CheckAngrenzendeFelder(ByVal X As Integer, ByVal Y As Integer, ByVal FeindlEinheiten As Boolean, ByVal Besetzung As Boolean) As Boolean
        Dim Rückgabe As Boolean = False
        Dim X2 As Integer = X
        Dim Y2 As Integer = Y
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If Objektverwalter.Spielfeld.OnMap(X2, Y2) = True Then
                If FeindlEinheiten = True Then
                    If KannFernkampfGemachtWerden(Einheit, X2, Y2) Then
                        If Rückgabe = False Then
                            Rückgabe = True
                            ZielPunkt = New Point(X2, Y2)
                        ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                            ZielPunkt = New Point(X2, Y2)
                        End If
                    End If
                    If KannNahkampfvonFeldgemachtwerden(Einheit, X2, Y2) = True Then
                        If Rückgabe = False Then
                            Rückgabe = True
                            ZielPunkt = New Point(X2, Y2)
                        ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                            ZielPunkt = New Point(X2, Y2)
                        End If
                    End If
                End If
                If Besetzung = True Then
                    If Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlacht) Is Nothing Then
                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X2, Y2, Schlacht).Gebäude
                        If Not G Is Nothing Then
                            If G.IsBesetzung(Einheit.Spieler) = True Then
                                If Rückgabe = False Then
                                    Rückgabe = True
                                    ZielPunkt = New Point(X2, Y2)
                                ElseIf getBewegungspunktekosten(ZielPunkt.X, ZielPunkt.Y) > getBewegungspunktekosten(X2, Y2) Then
                                    ZielPunkt = New Point(X2, Y2)
                                End If
                            End If
                        End If
                    End If
                End If
                addWegsucher(X2, Y2)
            End If
        Next
        Return Rückgabe
    End Function

    ''' <summary>
    ''' Fügt einen neuen Wegsucher hinzu. Es wird geprüft, ob das Feld existiert und ob es frei ist
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <remarks></remarks>
    Private Sub addWegsucher(ByVal X As Integer, ByVal Y As Integer, Optional ByVal Startfeld As Boolean = False)
        If FeldPrüfen(X, Y) = True Then
            If Startfeld = False Then
                If X = StartX And Y = StartY And Ini = True Then Exit Sub
                If DauerMax < 0 Then
                    Array.Resize(Wegsucher, Wegsucher.Length + 1)
                    Wegsucher(Wegsucher.Length - 1) = New Wegsucher
                    Wegsucher(Wegsucher.Length - 1).setPosition(X, Y, NeueDauer(Dauer, X, Y))
                    Suchfeld(X, Y) = NeueDauer(Dauer, X, Y)
                Else
                    If NeueDauer(Dauer, X, Y) <= DauerMax Then
                        Array.Resize(Wegsucher, Wegsucher.Length + 1)
                        Wegsucher(Wegsucher.Length - 1) = New Wegsucher
                        Wegsucher(Wegsucher.Length - 1).setPosition(X, Y, NeueDauer(Dauer, X, Y))
                        Suchfeld(X, Y) = NeueDauer(Dauer, X, Y)
                    End If
                End If
            Else
                Array.Resize(Wegsucher, Wegsucher.Length + 1)
                Wegsucher(Wegsucher.Length - 1) = New Wegsucher
                Wegsucher(Wegsucher.Length - 1).setPosition(X, Y, 0)
                Suchfeld(X, Y) = 0
            End If
        End If
    End Sub
    ''' <summary>
    ''' Fügt einen alten Wegsucher den Wegsuchern hinzu
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Dauer"></param>
    ''' <remarks></remarks>
    Public Sub addWegsucher(ByVal X As Integer, ByVal Y As Integer, ByVal Dauer As Integer)
        Array.Resize(Wegsucher, Wegsucher.Length + 1)
        Wegsucher(Wegsucher.Length - 1) = New Wegsucher
        Wegsucher(Wegsucher.Length - 1).setPosition(X, Y, Dauer)
    End Sub

    ''' <summary>
    ''' Prüft, ob das Feld Existiert und ob es frei ist, wenn ja dann True
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function FeldPrüfen(ByVal X As Integer, ByVal Y As Integer) As Boolean
        If X >= 0 And Y >= 0 And X < Objektverwalter.Spielfeld.Breite And Y < Objektverwalter.Spielfeld.Höhe Then
            If Suchfeld(X, Y) = Nothing Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    Private Function NeueDauer(ByVal Dauer As Integer, ByVal X As Integer, ByVal Y As Integer) As Integer
        Dim Wegkosten As Integer = Objektverwalter.Bewegungskosten(Einheit, Objektverwalter.Spielfeld.Landschaften(X, Y, Schlacht).getID, Objektverwalter.Spielfeld.Regeln.Wetter, X, Y)
        Return Dauer + Wegkosten
    End Function
    Public Function getBewegungspunktekosten(ByVal P As Point) As Integer
        Return getBewegungspunktekosten(P.X, P.Y)
    End Function
    Public Function getBewegungspunktekosten(ByVal X As Integer, ByVal Y As Integer) As Integer
        If X >= 0 And Y >= 0 And X < Objektverwalter.Spielfeld.Breite And Y < Objektverwalter.Spielfeld.Höhe Then
            If X = StartX And Y = StartY Then Return 0
            For Each Feld In Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).VeränderteWerte.VeränderteBewegungsFelder
                If Feld.X = X And Feld.Y = Y Then
                    Return Suchfeld(X, Y)
                End If
            Next
            If Suchfeld(X, Y) = 0 Then Return -1
            Return Suchfeld(X, Y)
        Else
            Return -1
        End If
    End Function
    Public Function GetSuchFeldWert(ByVal X As Integer, ByVal Y As Integer) As Integer
        If Objektverwalter.Spielfeld.OnMap(X, Y) = True Then
            If X = StartX And Y = StartY Then Return 1
            Return Suchfeld(X, Y)
        End If
    End Function


    ''' <summary>
    ''' Überprüft ob von diesem Feld per Nahangriff eine Einheit angegriffen werden kann
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfvonFeldgemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Not Einheit.Waffe1 = "Keine" Or Einheit.MinimaleReichweite = 1 Then
            Dim X2 As Integer = X
            Dim Y2 As Integer = Y
            For I = 0 To 3
                Select Case I
                    Case 0
                        X2 -= 1
                    Case 1
                        X2 += 1
                        Y2 -= 1
                    Case 2
                        X2 += 1
                        Y2 += 1
                    Case 3
                        X2 -= 1
                        Y2 += 1
                End Select
                If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                    If Einheit.IsAttackable(Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlacht), True) = True Then
                        Return True
                    End If
                End If
            Next
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgeführt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannFernkampfGemachtWerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim Felder As Point() = {}
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            If MaximaleReichweite > 1 Then
                Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                                If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlacht) Is Nothing Then
                                    If Einheit.IsAttackable(Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlacht), True) = True Then
                                        Return True
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function

    Public Function CanAttack(ByVal Einheit As ObjektEinheit, ByVal ZielKoordinaten As Point) As Boolean

    End Function
End Class
